package at.brandl.wwi;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class WhereWasIActivity extends ListActivity {

	private static final int DELETE_ID = Menu.FIRST;
	private static final int CLEANUP_ID = 0;
	private WhereWasIDbAdapter mDbHelper;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.points_list);

		startService(new Intent(this, WhereWasIService.class));

		mDbHelper = new WhereWasIDbAdapter(this);
		mDbHelper.open();

		fillData();

		registerForContextMenu(getListView());
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.add(Menu.NONE, DELETE_ID, Menu.NONE, R.string.delete);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case DELETE_ID:
			AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
					.getMenuInfo();
			mDbHelper.deletePoint(info.id);
			fillData();
			return true;
		}
		return super.onContextItemSelected(item);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, CLEANUP_ID, 0, R.string.cleanup);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case CLEANUP_ID:
			cleanUp();
			return true;
		}

		return super.onMenuItemSelected(featureId, item);
	}

	@Override
	protected void onDestroy() {
		mDbHelper.close();
		super.onDestroy();
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		Intent intent = new Intent(this, WhereWasIMapActivity.class);
		intent.putExtra(WhereWasIDbAdapter.KEY_ID, id);
		startActivity(intent);
	}

	private void fillData() {
		Cursor pointsCursor = mDbHelper.fetchAllPoints();
		startManagingCursor(pointsCursor);

		PointsAdapter points = new PointsAdapter(this, pointsCursor);
		setListAdapter(points);
	}

	private void cleanUp() {
		Cursor c = mDbHelper.fetchAllPoints();
		startManagingCursor(c);
		WhereWasIPoint lastPoint = null;
		while (c.moveToNext()) {
			WhereWasIPoint point = WhereWasIDbAdapter.convertToPoint(c);
			if (point.getAccuracy() > WhereWasIService.MAX_ACCURACY_METERS) {
				mDbHelper.deletePoint(point.getId());
				continue;
			}
			if (lastPoint == null) {
				lastPoint = point;
				continue;
			}
			if (overLap(lastPoint, point)) {
				if (point.getAccuracy() > lastPoint.getAccuracy()) {
					mDbHelper.deletePoint(point.getId());
				} else {
					mDbHelper.deletePoint(lastPoint.getId());
					lastPoint = point;
				}
			}
			else
			{
				lastPoint = point;
			}
		}
	}

	private boolean overLap(WhereWasIPoint lastPoint, WhereWasIPoint point) {
		return getDistance(lastPoint, point) < (lastPoint.getAccuracy() + point
				.getAccuracy());
	}

	private float getDistance(WhereWasIPoint lastPoint, WhereWasIPoint point) {
		float[] results = { 0 };
		Location.distanceBetween(lastPoint.getLatitude(),
				lastPoint.getLongitude(), point.getLatitude(),
				point.getLongitude(), results);
		return results[0];
	}

	private static class PointsAdapter extends CursorAdapter {
		private final LayoutInflater inflater;

		public PointsAdapter(Context context, Cursor cursor) {
			super(context, cursor, false);
			inflater = LayoutInflater.from(context);
		}

		@Override
		public View newView(Context context, Cursor cursor, ViewGroup parent) {
			return inflater.inflate(R.layout.point_row, parent, false);
		}

		@Override
		public void bindView(View view, Context context, Cursor cursor) {

			WhereWasIPoint point = WhereWasIDbAdapter.convertToPoint(cursor);

			// set time

			((TextView) view.findViewById(R.id.time)).setText(point
					.getDateString());

			// set latitude & longitude
			((TextView) view.findViewById(R.id.latitude)).setText(Location
					.convert(point.getLatitude(), Location.FORMAT_DEGREES));
			((TextView) view.findViewById(R.id.longitude)).setText(Location
					.convert(point.getLongitude(), Location.FORMAT_DEGREES));

			// set accuracy & boundary
			((TextView) view.findViewById(R.id.accuracy)).setText(point
					.getAccuracy() + " m");
			((TextView) view.findViewById(R.id.boundary)).setText(point
					.getBoundary() == null ? null : point.getBoundary()
					.getText());

		}
	}

}